klacki
Goto Top

Powershell Ordner dauerhaft überwachen und neue Dateien automatisch versenden

Hallo zusammen,

ich würde gerne einen Ordner überwachen lassen und sobald eine CSV-Datei dort abgelegt wird, soll diese automatisch per E-Mail versendet werden.
Soweit funktioniert es auch, aber wie bekomme ich es hin, dass der Ordner C:\test dauerhaft oder in xx Sekunden überwacht wird?

so schaut mein code bisher aus...

$SmtpUser = "xxx@xxx.de"  
$smtpPassword = "xxxx"  

$MailtTo = 'xyz@xxx.de'  
$MailFrom = "xxx@xxx,de"  
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $SmtpUser, $($smtpPassword | ConvertTo-SecureString -AsPlainText -Force)

#Variablen für Mail Subject, Body einrichten

$MailSubject = 'blabla'  
$MailBody = 
"<p>xxx,</p>  
<p>im Anhang finden Sie die Dateien.</p>"  

#Variablen für den Bericht der Angehängt werden soll deklarieren
$AttachmentDirectory = "C:\test"  
#$FileType= "csv" 

#Get-ChildItem -path $AttachmentDirectory -Recurse | Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject "$MailSubject" -Body "$MailBody" -SmtpServer $SmtpServer -BodyAsHtml -UseSsl -Credential $Credentials -Encoding ([System.Text.Encoding]::UTF8) 
#$Files | Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject "$MailSubject" -Body "$MailBody" -SmtpServer $SmtpServer -BodyAsHtml -UseSsl -Credential $Credentials -Encoding ([System.Text.Encoding]::UTF8) 

$Files = @(Get-ChildItem -path $AttachmentDirectory )
if ($Files.length -eq 0) {
  write-host "nothing todo"  
  exit
 
} else {
Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject "$MailSubject" -Body "$MailBody" -SmtpServer $SmtpServer -BodyAsHtml -Attachments $Files.Fullname -UseSsl -Credential $Credentials -Encoding ([System.Text.Encoding]::UTF8);  
Remove-item $Files.Fullname
}

Content-Key: 12734652017

Url: https://administrator.de/contentid/12734652017

Printed on: May 20, 2024 at 13:05 o'clock

Member: Crusher79
Crusher79 Oct 10, 2023 at 21:01:23 (UTC)
Goto Top
Hallo,

war schonmal Thema hier. Wenn du mal suchst....

Ansonsten ist das hier eine gute Anlaufstelle für Files und Events: https://powershell.one/tricks/filesystem/filesystemwatcher

mfg Crusher
Member: Celiko
Celiko Oct 10, 2023 updated at 21:13:28 (UTC)
Goto Top
Moin,

einfach ein scheduled task erstellen der alle X Minuten / Sekunden läuft.

Ich empfehle dir zumindest irgendein Log zu erstellen das die gelöschten Dateien / fehlerhaften Mails (Try-Catch) protokolliert.
Falls da mal was schief läuft löscht er die Dateien immer. Bspw. wenn Internet mal weg ist.

Weiß zwar nicht wie groß deine Anhänge sind aber wenn die mal zu groß sind können die Mails nicht zugestellt werden*.
Ggfs. nochmal die Größe der Anhänge auswerten und ein Limit setzen, damit daraus mehrere Mails generiert werden*

VG
Member: Doskias
Doskias Oct 11, 2023 at 06:14:45 (UTC)
Goto Top
Moin,

du solltest das Konstrukt ggf. auch noch an einer anderen Stelle überdenken. Zeile 2 bereitet mir doch arges Kopfzerbrechen. Ein Passwort in Klartext in einem Skript? Das muss nicht sein. das solltest du anders lösen.

Gruß
Doskias
Member: Kraemer
Kraemer Oct 11, 2023 at 06:41:23 (UTC)
Goto Top
Moin,

wie @Crusher79 schon ganz richtig schrieb, ist der FileSystemWatcher wahrscheinlich die eleganteste Lösung. Leider gibt es da einige Fallstricke zu beachten, wie z.B. der Fakt, dass es einige Zeit dauern kann, bis eine Datei fertig geschrieben ist.

"Send-MailMessage" solltest du wirklich nicht mehr verwenden:
Warning

The Send-MailMessage cmdlet is obsolete. This cmdlet does not guarantee secure connections to SMTP servers. While there is no immediate replacement available in PowerShell, we recommend you do not use Send-MailMessage.

Eine Alternative wäre z.B. https://github.com/jstedfast/MailKit

@Doskias: Das er das nicht tun sollte mag ja stimmen. Ohne dem TO eine Alternative vorzuschlagen ist dein Post allerdings sinnlos
Member: Crusher79
Crusher79 Oct 11, 2023 updated at 08:47:30 (UTC)
Goto Top
Generell ist E-Mail doch eher langsam.

Der erwähnte Watcher ist für Echtzeit Aufgaben nett. Wenn wir einfach unterstellen dass eine E-Mail eh etwas länger braucht und wir somit nicht binnen 1 Sekunde eine Antwort erwarten, so wäre der Taskplaner noch im rennen.

Damit sowas nicht doppelt und dreifeach läuft, wäre eine lck-file ggf. eine Hilfe. Ich blockiere damit in der Form, dass man die Function nicht aufrufen kann, wenn sie gerade am verabeiten ist.


Nur ein Vorschlag! Dass kannst du dann in 1 min. oder 5 min Tag im Taskplaner abfeuern. Man kann Timeoutes für den Mail-Versand und Error-Handling noch mit reinnehmen. Bei kürzen Intervallen verhindert die lck eine ungewolltes ausführen.

Alternativ wäre eine Schleife. Script bleibt 24 Std. im Hintergrund auf und vearbeitet die Dateien. Taskplaner + Lck-File ist aber auch sehr robust.

Verwaiste Lck-Dateien werden nach frühestens 10 min. automatisch gelöscht und es geht weiter ....


[string]$lckFile = "C:\temp\csv2mail.lck"  

Function MailCSV() {
$SmtpUser = "xxx@xxx.de"    
$smtpPassword = "xxxx"    

$MailtTo = 'xyz@xxx.de'    
$MailFrom = "xxx@xxx,de"    
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $SmtpUser, $($smtpPassword | ConvertTo-SecureString -AsPlainText -Force)

#Variablen für Mail Subject, Body einrichten

$MailSubject = 'blabla'    
$MailBody = 
"<p>xxx,</p>    
<p>im Anhang finden Sie die Dateien.</p>"    

#Variablen für den Bericht der Angehängt werden soll deklarieren
$AttachmentDirectory = "C:\test"    
#$FileType= "csv"   

#Get-ChildItem -path $AttachmentDirectory -Recurse | Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject "$MailSubject" -Body "$MailBody" -SmtpServer $SmtpServer -BodyAsHtml -UseSsl -Credential $Credentials -Encoding ([System.Text.Encoding]::UTF8)   
#$Files | Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject "$MailSubject" -Body "$MailBody" -SmtpServer $SmtpServer -BodyAsHtml -UseSsl -Credential $Credentials -Encoding ([System.Text.Encoding]::UTF8)   

$Files = @(Get-ChildItem -path $AttachmentDirectory )
if ($Files.length -eq 0) {
  write-host "nothing todo"    
  exit
 
} else {
Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject "$MailSubject" -Body "$MailBody" -SmtpServer $SmtpServer -BodyAsHtml -Attachments $Files.Fullname -UseSsl -Credential $Credentials -Encoding ([System.Text.Encoding]::UTF8);    
Remove-item $Files.Fullname
}
}

Function Script:WriteLog() {
            Param ([string]$LogString)
            $LogFile = "C:\temp\logs\$(gc env:computername).log"  
            $DateTime = "[{0:dd/MM/yyyy} {0:HH:mm:ss}]" -f (Get-Date)  
            $LogMessage = "$Datetime $LogString"  
            Add-content $LogFile -value $LogMessage
            }

Function CreateLckFile() { 
            $null = New-Item -ItemType "file" -Path $lckFile;   
            # Fix NTFS Tunnellig
            $(Get-Item -Force $lckFile).CreationTime = $(Get-Item -Force $lckFile).LastWriteTime; 
            }

Function LckTimeDiff() {
            $lckFileCreationTime = $((Get-Item $lckFile).CreationTime)
            $Diffobj = $(Get-Date) - $lckFileCreationTime
            [int]$Script:DiffInMin = [int]$Diffobj.TotalMinutes
            }

Function LckAndStart() {  
    if (! (Test-path -path $lckFile)) {
        CreateLckFile
        WriteLog "Lck Erstellt"  
        MailCSV
        WriteLog "Versand abgeschlossen"         
        Remove-Item $lckFile -Force
    } else { 
        LckTimeDiff                            
        IF ($DiffInMin -gt 10 ) {                            
            WriteLog "Alte Lck vorhanden"  
            Remove-Item $lckFile -Force   
            CreateLckFile
            WriteLog "Lck neu erstellt"  
            MailCSV
            WriteLog "Versand abgeschlossen"     
            Remove-Item $lckFile -Force                
            } 

    }
}
LckAndStart; 
Member: Doskias
Doskias Oct 11, 2023 at 11:15:22 (UTC)
Goto Top
Zitat von @Kraemer:
@Doskias: Das er das nicht tun sollte mag ja stimmen. Ohne dem TO eine Alternative vorzuschlagen ist dein Post allerdings sinnlos

Nein ist es nicht. und ich erkläre dir auch gerne wieso: Um eine wirkliche Alternative vorzuschlagen, kenne ich die Umgebung nicht. Da fängt es ja schon an ob der Mail-Server intern oder extern ist, wie sein Zugriff auf den Mailserver ist und was die Firmenrichtlinien vorschreiben. Und es steht doch schon da:

Zitat von @Celiko:
einfach ein scheduled task erstellen der alle X Minuten / Sekunden läuft.
Das könnte schon die Lösung sein, aber dazu kenne ich die Umgebung zu wenig.

Was ich aber, unabhängig von der Umgebung, sagen kann, ist, dass ein Passwort in Klartext in kein Skript gehört. Das ist eine grundlegende Sache, die nur am Rande etwas mit dem Problem zu tun hat.

Gruß
Doskias
Member: Celiko
Celiko Oct 11, 2023 at 11:36:10 (UTC)
Goto Top
Long story short, der TO muss jetzt eine Info geben, ob die genannten Lösungsansätze für ihn verständlich und passend sind oder nicht.
Er wird sich vermutlich bzgl. des Passwortes in Klartext etwas gedacht haben. Hoffentlich 😁

VG